package org.microframework.cloud.gateway.config;

import com.alibaba.cloud.nacos.NacosConfigManager;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import jakarta.annotation.PostConstruct;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;

/**
 * Nacos路由配置加载器
 * 监听Nacos配置变化，动态更新路由
 * 注意：此配置类仅在启用Nacos配置时生效
 */
@Slf4j
@Component
@Configuration
@ConditionalOnProperty(name = "spring.cloud.nacos.config.enabled", havingValue = "true", matchIfMissing = true)
public class NacosRouteConfigLoader {

    @Autowired
    private DynamicRouteConfig dynamicRouteConfig;

    @Autowired
    private NacosConfigManager nacosConfigManager;

    @Autowired
    private ObjectMapper objectMapper;

    @Value("${spring.cloud.nacos.config.group:DEFAULT_GROUP}")
    private String group;

    @Value("${spring.application.name}")
    private String applicationName;

    @Value("${spring.cloud.gateway.nacos.routes-data-id:${spring.application.name}-routes.json}")
    private String routesDataId;

    // 当前已加载的路由缓存
    private Map<String, RouteDefinition> routeCache = new HashMap<>();

    @PostConstruct
    public void init() {
        try {
            log.info("开始从Nacos加载路由配置，dataId={}, group={}", routesDataId, group);
            ConfigService configService = nacosConfigManager.getConfigService();
            String configInfo = configService.getConfig(routesDataId, group, 5000);
            
            if (StringUtils.hasText(configInfo)) {
                log.info("从Nacos初始化路由配置：{}", configInfo);
                updateRoutes(configInfo);
            } else {
                log.warn("Nacos中未找到路由配置，dataId={}, group={}", routesDataId, group);
            }
            
            // 添加监听器
            configService.addListener(routesDataId, group, new Listener() {
                @Override
                public Executor getExecutor() {
                    return null;
                }

                @Override
                public void receiveConfigInfo(String configInfo) {
                    log.info("接收到Nacos路由配置更新：{}", configInfo);
                    updateRoutes(configInfo);
                }
            });
            
            log.info("Nacos路由配置监听器已启动");
        } catch (NacosException e) {
            log.error("初始化Nacos路由配置失败: {}", e.getMessage(), e);
        }
    }

    /**
     * 更新路由配置
     */
    private void updateRoutes(String configInfo) {
        if (!StringUtils.hasText(configInfo)) {
            log.warn("路由配置为空");
            return;
        }

        try {
            List<RouteDefinition> routeDefinitions = objectMapper.readValue(configInfo, 
                    new TypeReference<List<RouteDefinition>>() {});
            
            // 创建新的路由缓存
            Map<String, RouteDefinition> newRouteCache = new HashMap<>();
            
            // 添加/更新路由
            for (RouteDefinition definition : routeDefinitions) {
                String routeId = definition.getId();
                newRouteCache.put(routeId, definition);
                
                // 如果是新增或更新的路由
                if (!routeCache.containsKey(routeId) || !routeCache.get(routeId).equals(definition)) {
                    log.info("更新路由: {}", routeId);
                    String result = dynamicRouteConfig.update(definition);
                    if (!"success".equals(result)) {
                        log.warn("更新路由[{}]失败: {}", routeId, result);
                    }
                }
            }
            
            // 删除不再存在的路由
            for (String oldRouteId : routeCache.keySet()) {
                if (!newRouteCache.containsKey(oldRouteId)) {
                    log.info("删除路由: {}", oldRouteId);
                    String result = dynamicRouteConfig.delete(oldRouteId);
                    if (!"success".equals(result)) {
                        log.warn("删除路由[{}]失败: {}", oldRouteId, result);
                    }
                }
            }
            
            // 更新缓存
            routeCache = newRouteCache;
            log.info("路由配置更新完成，共{}个路由", routeCache.size());
            
        } catch (JsonProcessingException e) {
            log.error("解析路由配置失败: {}", e.getMessage(), e);
        } catch (Exception e) {
            log.error("更新路由配置失败: {}", e.getMessage(), e);
        }
    }
} 